﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Santa_sAdventure.Model;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Santa_sAdventure.Model.Enums;
using Microsoft.Xna.Framework.Content;
using System.IO;

namespace Santa_sAdventure.View
{
    class GameView
    {
        // Classes
        private Camera m_camera;
        private SnowSystem m_snowSystem;
        private Texture2D m_snowParticleTexture;
        // Font
        private SpriteFont m_font;

        // Construct
        internal GameView(Camera a_camera, Texture2D a_snowParticleTexture, ContentManager a_content)
        {
            // Set classes
            m_camera = a_camera;
            m_snowSystem = new SnowSystem();
            m_snowParticleTexture = a_snowParticleTexture;
            // Font             
            m_font = a_content.Load<SpriteFont>("SpriteFont1");
        }

        // Draw level
        internal void DrawLevel(Level a_level, SpriteBatch a_spriteBatch, ContentManager a_content, Player a_player, float a_time)
        {
            // Draw and Update particles
            m_snowSystem.Update(a_time);
            m_snowSystem.Draw(a_spriteBatch, m_camera, m_snowParticleTexture);


            Tile[,] tiles = a_level.GetTiles();
            // Draw Level
            for (int x = 0; x < a_level.Width; x++)
            {
                for (int y = 0; y < a_level.Height; y++)
                {
                    if (tiles[x, y].GetTileType() == TileType.Solid ||
                        tiles[x, y].GetTileType() == TileType.Trap)
                    {
                        Rectangle tileRec = m_camera.GetVisualRectangle(x, y, (int)tiles[x, y].GetTileSize().X, (int)tiles[x, y].GetTileSize().Y);
                        // Set random texture if none is set
                        Texture2D tileTexture = null;
                        if (!tiles[x,y].HaveTexture())
                        {
                            Random rnd = new Random(x);
                            // It´s a solid
                            if (tiles[x, y].GetTileType() == TileType.Solid)
                            {
                                // Check how many different tiletextures there is
                                string[] files = Directory.GetFiles("Content/Images/Tiles/Solid");
                                int index = rnd.Next(0, files.Count());
                                tileTexture = a_content.Load<Texture2D>(string.Format("Images/Tiles/Solid/Solid{0}", index));
                                tiles[x, y].SetTexture(tileTexture);
                            }
                            // It´s a trap
                            else if (tiles[x, y].GetTileType() == TileType.Trap)
                            {
                                tileTexture = a_content.Load<Texture2D>("Images/Tiles/Trap/Trap");
                                tiles[x, y].SetTexture(tileTexture);
                            }
                            
                        }
                        else
                        {
                            tileTexture = tiles[x, y].GetTexture();
                        }
                        // Draw the tile
                        a_spriteBatch.Draw(tileTexture, tileRec, Color.White);
                    }                    
                }
            }

            // Draw all the packets in the level
            var packets = a_level.GetPackets();
            if (packets != null)
            {
                for (int i = 0; i < packets.Count; i++)
                {
                    if (!packets[i].IsTaken)
                    {
                        Rectangle packetRec = m_camera.GetVisualRectangle(packets[i].Position.X, packets[i].Position.Y,
                                                 packets[i].Size.X, packets[i].Size.Y);
                        a_spriteBatch.Draw(a_content.Load<Texture2D>("Images/Packets/packet"), packetRec, Color.White);
                    }
                }
            }

            // Draw player and ememies
            Rectangle playerRec = m_camera.GetVisualRectangle(a_player.Position.X, a_player.Position.Y, a_player.Size.X, a_player.Size.Y);
            //a_spriteBatch.Draw(a_content.Load<Texture2D>("Images/Player/Idle"), playerRec, Color.White);

            var enemies = a_level.GetEnemies();
            if (enemies != null)
            {
                for (int i = 0; i < enemies.Count; i++)
                {
                    // Enemy rec
                    Rectangle enemyRec = m_camera.GetVisualRectangle(enemies[i].Position.X, enemies[i].Position.Y,
                                                enemies[i].Size.X, enemies[i].Size.Y);
                    //a_spriteBatch.Draw(a_content.Load<Texture2D>("Images/Enemy/idle-enemy-stretched-2"), enemyRec, Color.White);

                    // Draw animation                        
                    enemies[i].GetAnimationPlayer().DrawAndUpdate(a_time, a_spriteBatch, enemyRec, enemies[i].GetSpriteEffect());

                    // Draw bullets
                    if (enemies[i] is ShootingEnemy)
                    {
                        var bullets = (enemies[i] as ShootingEnemy).GetAllBullets;
                        for (int j = 0; j < bullets.Count; j++)
                        {
                            Rectangle bulletRec = m_camera.GetVisualRectangle(bullets[j].Position.X, bullets[j].Position.Y, bullets[j].Size.X, bullets[j].Size.Y);

                            SpriteEffects spriteEffects = bullets[j].GetSpriteEffect();
                            a_spriteBatch.Draw(a_content.Load<Texture2D>("Images/Bullets/bullet-filled"), bulletRec, null, Color.White, 0.0f, Vector2.Zero, spriteEffects, 0.0f);
                        }
                    }
                }
            }


            // Draw the exit
            Rectangle exitRec = m_camera.GetVisualRectangle(a_level.ExitPosition.X, a_level.ExitPosition.Y - 1, 1, 2);
            a_spriteBatch.Draw(a_content.Load<Texture2D>("Images/Elements/Exit/chimney"), exitRec, Color.White);

            

            var packetTextRec = m_camera.GetVisualRectangle(1, 1, 1, 1);
            Vector2 packetTextShadow = new Vector2(packetTextRec.X + 2f, packetTextRec.Y + 2f);
            var enemiesTextRec = m_camera.GetVisualRectangle(1, 2, 1, 1);
            Vector2 enemiesTextShadow = new Vector2(enemiesTextRec.X + 2f, enemiesTextRec.Y + 2f);
            var lifesTextRec = m_camera.GetVisualRectangle(1, 3, 1, 1);
            Vector2 lifesTextShadow = new Vector2(lifesTextRec.X + 2f, lifesTextRec.Y + 2f);
            var timeTextRec = m_camera.GetVisualRectangle(1, 4, 1, 1);
            Vector2 timeTextShadow = new Vector2(timeTextRec.X + 2f, timeTextRec.Y + 2f);
            // Nr of Packets taken
            a_spriteBatch.DrawString(m_font, "Packets: " + a_level.GetNumberOfPacketsTaken().ToString() + " / " + a_level.GetPackets().Count, packetTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, "Packets: " + a_level.GetNumberOfPacketsTaken().ToString() + " / " + a_level.GetPackets().Count, new Vector2(packetTextRec.X, packetTextRec.Y), Color.White);
            // Nr of enemies killed
            a_spriteBatch.DrawString(m_font, "Enemies killed: " + a_level.GetNumberOfEnemieKilled() + " / " + a_level.GetEnemies().Count, enemiesTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, "Enemies killed: " + a_level.GetNumberOfEnemieKilled() + " / " + a_level.GetEnemies().Count, new Vector2(enemiesTextRec.X, enemiesTextRec.Y), Color.White);
            // Lifes left
            a_spriteBatch.DrawString(m_font, "Lifes: " + a_player.NrOfLifes.ToString(), lifesTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, "Lifes: " + a_player.NrOfLifes.ToString(), new Vector2(lifesTextRec.X, lifesTextRec.Y), Color.White);
            // Time
            a_spriteBatch.DrawString(m_font, String.Format("Time: {0:F1} Sec", a_level.TimeElapsed), timeTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, String.Format("Time: {0:F1} Sec", a_level.TimeElapsed), new Vector2(timeTextRec.X, timeTextRec.Y), Color.White);

            // Draw level specific help text
            var helpTextRec = m_camera.GetVisualRectangle(3, 7, 1, 1);
            Vector2 helpTextShadow = new Vector2(helpTextRec.X + 2f, helpTextRec.Y + 2f);
            a_spriteBatch.DrawString(m_font, a_level.GetHelpText(), helpTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, a_level.GetHelpText(), new Vector2(helpTextRec.X, helpTextRec.Y), Color.White);


            // Draw animation
            a_player.GetAnimationPlayer().DrawAndUpdate(a_time, a_spriteBatch, playerRec, a_player.GetSpriteEffect());

        }

        // If player wants to jump
        internal bool DidPlayerJump()
        {
            // State
            KeyboardState keyboardState = Keyboard.GetState();
            // Jump key
            Keys jumpKey = Keys.Up;

            if (keyboardState.IsKeyDown(jumpKey))
            {
                return true;
            }
            return false;
        }

        // If player wants to go left
        internal bool DidPlayerPressLeft()
        {
            // State
            KeyboardState keyboardState = Keyboard.GetState();
            // Left key
            Keys leftKey = Keys.Left;

            if (keyboardState.IsKeyDown(leftKey))
            {
                return true;
            }
            return false;
        }

        // If player wants to go right
        internal bool DidPlayerPressRight()
        {
            // State
            KeyboardState keyboardState = Keyboard.GetState();
            // Right key
            Keys rightKey = Keys.Right;

            if (keyboardState.IsKeyDown(rightKey))
            {
                return true;
            }
            return false;
        }

        // If player want sto pause the game
        internal bool DidPlayerPause()
        {
            // State
            KeyboardState keyboardState = Keyboard.GetState();
            // Pause key
            Keys pauseKey = Keys.P;

            if (keyboardState.IsKeyDown(pauseKey))
            {
                return true;
            }
            return false;
        }

       


        // If user wants to continue to play after death or level completion
        internal bool DidPlayerContinue()
        {
            // State
            KeyboardState keyboardState = Keyboard.GetState();
            // Continue key
            Keys continueKey = Keys.Up;

            if (keyboardState.IsKeyDown(continueKey))
            {
                return true;
            }
            return false;
        }

        // Draw final stats on the level
        internal void DrawLevelStats(Level a_level, SpriteBatch a_spriteBatch, ContentManager a_content, Player a_player)
        {
            var packetTextRec = m_camera.GetVisualRectangle(a_level.Width / 2 -2 , a_level.Height / 2 -4 , 1, 1);
            Vector2 packetTextShadow = new Vector2(packetTextRec.X + 2f, packetTextRec.Y + 2f);
            var enemiesTextRec = m_camera.GetVisualRectangle(a_level.Width / 2 - 2, a_level.Height / 2 - 3, 1, 1);
            Vector2 enemiesTextShadow = new Vector2(enemiesTextRec.X + 2f, enemiesTextRec.Y + 2f);
            var lifesTextRec = m_camera.GetVisualRectangle(a_level.Width / 2 - 2, a_level.Height / 2 - 2, 1, 1);
            Vector2 lifesTextShadow = new Vector2(lifesTextRec.X + 2f, lifesTextRec.Y + 2f);
            var timeTextRec = m_camera.GetVisualRectangle(a_level.Width / 2 - 2, a_level.Height / 2 - 1, 1, 1);
            Vector2 timeTextShadow = new Vector2(timeTextRec.X + 2f, timeTextRec.Y + 2f);
            var scoreTextRec = m_camera.GetVisualRectangle(a_level.Width / 2 - 2, a_level.Height / 2 -0, 1, 1);
            Vector2 scoreTextShadow = new Vector2(scoreTextRec.X + 2f, scoreTextRec.Y + 2f);
            // Nr of Packets taken
            a_spriteBatch.DrawString(m_font, "Packets: " + a_level.GetNumberOfPacketsTaken().ToString() + " / " + a_level.GetPackets().Count, packetTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, "Packets: " + a_level.GetNumberOfPacketsTaken().ToString() + " / " + a_level.GetPackets().Count, new Vector2(packetTextRec.X, packetTextRec.Y), Color.White);
            // Nr of enemies killed
            a_spriteBatch.DrawString(m_font, "Enemies killed: " + a_level.GetNumberOfEnemieKilled() + " / " + a_level.GetEnemies().Count, enemiesTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, "Enemies killed: " + a_level.GetNumberOfEnemieKilled() + " / " + a_level.GetEnemies().Count, new Vector2(enemiesTextRec.X, enemiesTextRec.Y), Color.White);
            // Lifes left
            a_spriteBatch.DrawString(m_font, "Lifes: " + a_player.NrOfLifes.ToString(), lifesTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, "Lifes: " + a_player.NrOfLifes.ToString(), new Vector2(lifesTextRec.X, lifesTextRec.Y), Color.White);
            // Time
            a_spriteBatch.DrawString(m_font, String.Format("Time: {0:F1} Sec", a_level.TimeElapsed), timeTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, String.Format("Time: {0:F1} Sec", a_level.TimeElapsed), new Vector2(timeTextRec.X, timeTextRec.Y), Color.White);
            // Score
            a_spriteBatch.DrawString(m_font, String.Format("Total score: {0}", a_level.TotalScore(a_player) ), scoreTextShadow, Color.Black);
            a_spriteBatch.DrawString(m_font, String.Format("Total score: {0}", a_level.TotalScore(a_player) ), new Vector2(scoreTextRec.X, scoreTextRec.Y), Color.White);
        }

        // Draw resume btn
        internal void DrawResumeBtn(Controller.Buttons.MenuButton a_resumeBtn, SpriteBatch a_spriteBatch)
        {
            a_resumeBtn.Draw(a_spriteBatch);
        }

        // Draw text
        internal void DrawText(string a_message, Vector2 a_position, SpriteBatch a_spriteBatch, int a_scale)
        {
            var textRec = m_camera.GetVisualRectangle(a_position.X, a_position.Y, 1, 1);
            a_spriteBatch.DrawString(m_font, a_message, new Vector2(textRec.X, textRec.Y), Color.Red, 0, Vector2.Zero, a_scale, SpriteEffects.None, 0);
        }
    }
}
